#ifndef PROCESSMONITOR_H
#define PROCESSMONITOR_H

#pragma once

#include <QObject>
#include <QProcess>
#include <QTimer>
#include <QDebug>
#include <QFile>
#include <QTextStream>

#ifdef Q_OS_WIN
#include <windows.h>
#include <psapi.h>
#pragma comment(lib, "psapi.lib")
#endif

class ProcessMonitor : public QObject
{
    Q_OBJECT

public:
    explicit ProcessMonitor(QObject *parent = nullptr)
        : QObject(parent), process(new QProcess(this)), checkTimer(new QTimer(this))
    {
        connect(process, &QProcess::started, this, [this]() {
            qDebug() << "[Monitor]" << programPath << " started, PID:" << process->processId();
        });
        connect(process, &QProcess::readyReadStandardOutput, this, [=]() {
            QByteArray out = process->readAllStandardOutput();

            qDebug() << "[Monitor]" << out;
        });
        connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
                this, [this](int code, QProcess::ExitStatus status){
            qDebug() << "[Monitor]" << programPath << " exited, code:" << code << " status:" << status;
        });
        connect(process, &QProcess::errorOccurred, this, [this](QProcess::ProcessError err) {
            qDebug() << "[Monitor]" << programPath << " error:" << err;
        });

        connect(checkTimer, &QTimer::timeout, this, &ProcessMonitor::checkStatus);
        checkTimer->setInterval(2000); // 默认2秒
    }

    void setProgram(const QString &path, const QStringList &args = {})
    {
        programPath = path;
        programArgs = args;
    }
    bool m_autoBoot = false;
    void enableAutoRebot(bool value){m_autoBoot = value;}
    void start()
    {
        if (programPath.isEmpty()) {
            qWarning() << "[Monitor] Program path is empty!";
            return;
        }

        if (process->state() != QProcess::NotRunning) {
            qDebug() << "[Monitor] Process already running.";
            return;
        }

        process->start(programPath, programArgs);
        checkTimer->start();
    }

    void stop()
    {
        checkTimer->stop();
        if (process->state() == QProcess::Running) {
            process->terminate();
            if (!process->waitForFinished(3000))
                process->kill();
        }
    }

    void setCheckInterval(int ms) { checkTimer->setInterval(ms); }

signals:
    void memoryUsageUpdated(qint64 bytes);
    void processCrashed();

private slots:
    void checkStatus()
    {
        if (process->state() == QProcess::Running) {
            qint64 pid = process->processId();
            qint64 mem = getMemoryUsage(pid);
            emit memoryUsageUpdated(mem);
        } else {
            emit processCrashed();
            if(m_autoBoot){
                process->start(programPath, programArgs);
            }

        }
    }

private:
    QProcess *process;
    QTimer *checkTimer;
    QString programPath;
    QStringList programArgs;

    qint64 getMemoryUsage(qint64 pid)
    {
#ifdef Q_OS_LINUX
        QFile file(QString("/proc/%1/status").arg(pid));
        if (file.open(QIODevice::ReadOnly)) {
            QTextStream in(&file);
            QString line;
            while (!in.atEnd()) {
                line = in.readLine();
                if (line.startsWith("VmRSS:")) { // 常驻内存
                    QStringList parts = line.split(QRegExp("\\s+"));
                    qDebug()<<"mem "<<parts;
                    if (parts.size() >= 2)
                        return parts[1].toLongLong() * 1024; // 转字节
                }
            }
        }
        return 0;

#elif defined(Q_OS_WIN)
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, (DWORD)pid);
        if (hProcess) {
            PROCESS_MEMORY_COUNTERS pmc;
            if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
                CloseHandle(hProcess);
                return pmc.WorkingSetSize; // 常驻内存字节
            }
            CloseHandle(hProcess);
        }
        return 0;
#else
        return 0;
#endif
    }
};



#endif // PROCESSMONITOR_H
